﻿using System;
using System.Collections.Generic;
using System.Windows.Forms;
using System.Runtime.InteropServices;   //调用WINDOWS API函数时要用到
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
using DoublyUtils;
using System.Collections.Specialized;
using static System.Windows.Forms.DataFormats;

namespace MyClipboardApplication
{
    public partial class MainForm : Form
    {
        //表示程序加载是否完成
        private Boolean loadComplete = false;
        private Boolean systemChange = true;
        private readonly String fileName = "Clipboard.doubly";
        private String filePath = String.Empty;
        private String directoryName = "ClipboardFiles";
        private String directoryPath = String.Empty;


        private ClipboardUtils clipboardUtils = new ClipboardUtils();
        private LogUtils log = LogUtils.getInstance(typeof(MainForm));


        public MainForm(String[] args)
        {
            InitializeComponent();

            for(int i = 0; i < args.Length; i += 2)
            {
                if (args[i].Equals("-dir"))
                {
                    this.txtPath.Text = args[i + 1];
                }
            }
        }

        //剪贴板监控
        [DllImport("User32.dll", CharSet = CharSet.Auto)]
        public static extern IntPtr SetClipboardViewer(IntPtr hWnd);

        [DllImport("User32.dll", CharSet = CharSet.Auto)]
        public static extern bool ChangeClipboardChain(IntPtr hWndRemove, IntPtr hWndNewNext);
        IntPtr ClipboardViewerNext;
        private void RegisterClipboardViewer()
        {
            ClipboardViewerNext = SetClipboardViewer(this.Handle);
        }

        private void UnregisterClipboardViewer()
        {
            ChangeClipboardChain(this.Handle, ClipboardViewerNext);
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            log.info("程序初始化");
            RegisterClipboardViewer();

            //clipboardUtils.pathCombine(this.txtPath.Text + "\\" + clipboardUtils.directoryName, true);
            if (!Directory.Exists(this.txtPath.Text))
            {
                MessageBox.Show("请设置共享文件夹路径");
                this.txtPath_Click(null, null);
            }

            //createFile();
            if (this.txtPath.Text.Length == 0) return; 
            if (this.txtPath.Text[this.txtPath.Text.Length - 1].Equals(Path.VolumeSeparatorChar))
            {
                this.txtPath.Text += Path.DirectorySeparatorChar;
            }
            this.filePath = Path.Combine(this.txtPath.Text, this.fileName);
            this.directoryPath = Path.Combine(this.txtPath.Text, this.directoryName);

            this.loadComplete = true;
        }

        /// <summary>
        /// 重写windows消息响应
        /// </summary>
        /// <param name="m"></param>
        protected override void WndProc(ref Message m)
        {
            const int WM_DRAWCLIPBOARD = 0x308;
            switch (m.Msg)
            {
                case WM_DRAWCLIPBOARD:
                    if (this.systemChange || this.chkSwitch.CheckState == CheckState.Unchecked || this.loadComplete == false)
                    {
                        break;
                    }
                    else
                    {
                        log.info("检测到复制操作");
                        var clipboardData = new Dictionary<String, Object>();
                        var dataObject = Clipboard.GetDataObject();

                        if (Clipboard.ContainsFileDropList())
                        {
                            //拷贝文件到共享目录即可
                            clipboardUtils.saveFiles(this.directoryPath);
                            clipboardData.Add(DataFormats.FileDrop, "copy files or directories");
                        }
                        else
                        {

                            var formats = dataObject.GetFormats();
                            foreach (var format in formats)
                            {
                                try
                                {
                                    //不知道什么原因EnhancedMetafile格式会抛外部异常
                                    //Windows 增强型图元文件格式
                                    /*if (format.Equals(DataFormats.EnhancedMetafile))
                                        continue;*/
                                    Object data = Clipboard.GetData(format);
                                    log.info("粘贴格式为" + format + "，内容为：" + data);

                                    Format formatObj = DataFormats.GetFormat(format);
                                    log.info(formatObj.Id + " => " + formatObj.Name);

                                    clipboardData.Add(format, data);
                                }catch(Exception ex)
                                {
                                    log.error(format + "格式存储失败");
                                    log.error(ex.Message);
                                }
                            }
                        }

                    FileStream fs = new FileStream(this.filePath, FileMode.Create, FileAccess.Write, FileShare.None);

                    BinaryFormatter bf = new BinaryFormatter();
                    bf.Serialize(fs, clipboardData);

                    fs.Close();
                        
                        log.info("复制内容序列化完成");
                    }
                    break;
                default :

                    base.WndProc(ref m);
                    break;
            }
            
        }

        private void txtPath_Click(object sender, EventArgs e)
        {
            this.folderBrowserDialog.ShowDialog();
            String path = this.folderBrowserDialog.SelectedPath;
            if (String.IsNullOrEmpty(path))
            {
                return;
            }
            log.info("切换共享路径");
            deleteFile();
            this.txtPath.Text = path;

            this.filePath = Path.Combine(this.txtPath.Text, this.fileName);
            this.directoryPath = Path.Combine(this.txtPath.Text, this.directoryName);
        }

        /// <summary>
        /// 删除临时文件
        /// </summary>
        private void deleteFile()
        {
            try
            {
                if (DirectoryUtils.deleteDirectory(this.directoryPath))
                {
                    if(Directory.Exists(this.directoryPath)) Directory.Delete(this.directoryPath);
                }

                if (!String.IsNullOrEmpty(this.filePath) && File.Exists(this.filePath))
                {
                    log.info("delete temp file");
                    File.Delete(this.filePath);
                }
            }
            catch (Exception ex)
            {
                log.error(ex.Message);
                log.error(ex.StackTrace);
            }
        }

        private void MainForm_FormClosed(object sender, FormClosedEventArgs e)
        {
            deleteFile();
        }

        private void notifyIcon_Click(object sender, EventArgs e)
        {
            if (this.WindowState == FormWindowState.Minimized)
            {
                this.ShowInTaskbar = true;
                this.WindowState = FormWindowState.Normal;
                this.Activate();
                RegisterClipboardViewer();
                //Console.WriteLine(this.Handle.ToInt32());
            }
        }

        private void MainForm_SizeChanged(object sender, EventArgs e)
        {
            if (this.WindowState == FormWindowState.Minimized)
            {
                //this.txtPath_Leave(null, null);
                this.ShowInTaskbar = false;
                FormHelper.HideTabAltMenu(this.Handle);
                RegisterClipboardViewer();
            }
        }

        private void chkSwitch_CheckedChanged(object sender, EventArgs e)
        {
            if (this.chkSwitch.CheckState == CheckState.Unchecked)
            {
                log.info("功能关闭");
            }
            else
            {
                log.info("功能开启");
            }
        }

        private DateTime lastUpdateTime = DateTime.Now;
        private void timer_Tick(object sender, EventArgs e)
        {
            if (this.chkSwitch.CheckState == CheckState.Unchecked || this.loadComplete == false) return;

            DateTime time = File.GetLastWriteTime(this.filePath);
            if (DateTime.Compare(lastUpdateTime, time) == 0)
            {
                return;
            }
            lastUpdateTime = time;
            //将系统修改开关置为true，表示剪贴板内容变动由程序改变，无需作出响应
            this.systemChange = true;
            clipboardUtils.setClipboard(this.filePath,this.directoryPath);
            this.systemChange = false;
        }

        /*
        private void txtPath_KeyDown(object sender, KeyEventArgs e)
        {
            if(e.KeyCode == Keys.Enter)
            {
                this.txtPath_Leave(sender, null);
            }
        }

        private void txtPath_Leave(object sender, EventArgs e)
        {
            //如果类似E:，则加上分隔符，E:\\
            if (this.txtPath.Text[this.txtPath.Text.Length - 1].Equals(Path.VolumeSeparatorChar))
            {
                this.txtPath.Text += Path.DirectorySeparatorChar;
            }
            if (!Directory.Exists(this.txtPath.Text))
            {
                MessageBox.Show("路径不存在，将使用原路径");
                this.txtPath.Focus();
            }
        }

        private void txtPath_TextChanged(object sender, EventArgs e)
        {
            if (String.IsNullOrEmpty(this.txtPath.Text))
            {
                this.txtPath.Focus();
                return;
            }
            if (!Directory.Exists(this.txtPath.Text))
            {
                this.txtPath.Focus();
                return;
            }
            log.info("切换共享路径");
            deleteFile();
            this.filePath = Path.Combine(this.txtPath.Text, this.fileName);
            this.directoryPath = Path.Combine(this.txtPath.Text, this.directoryName);
        }

        
        private void MainForm_Click(object sender, EventArgs e)
        {
            this.label1.Focus();
        }

        private void MainForm_Deactivate(object sender, EventArgs e)
        {
            this.label1.Focus();
        }

        private void MainForm_Leave(object sender, EventArgs e)
        {
            this.label1.Focus();
        }

        private void label1_Click(object sender, EventArgs e)
        {
            this.label1.Focus();
        }

        private void label2_Click(object sender, EventArgs e)
        {
            this.label1.Focus();
        }
        */
    }
}
